package org.qing.cloud.commons.config.mysql;

import java.lang.reflect.Field;
import java.time.Duration;

import org.qing.cloud.commons.utils.json.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
import org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager;
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
import org.springframework.transaction.ReactiveTransactionManager;
import org.springframework.util.StringUtils;

import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.ConnectionFactoryOptions;
import io.r2dbc.spi.ConnectionFactoryOptions.Builder;
import io.r2dbc.spi.Option;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
@EnableR2dbcRepositories
@EnableConfigurationProperties(R2dbcProperties.class)
@ConditionalOnProperty(prefix="spring.r2dbc",name = "driver", havingValue = "mysql")
public class R2dbcConfig extends AbstractR2dbcConfiguration {
	
	private final String CONNECT_TIMEOUT_VALUE = "connectTimeout";
	private final String USERNAME_KEY = "username";
	private final String USER_KEY = "user";
	
	@Autowired
	private R2dbcProperties r2dbcProperties;

	@Bean
	@Override
	public ConnectionFactory connectionFactory() {
		log.info("r2dbcProperties=[{}]", JSON.toJSONString(r2dbcProperties));
		Builder builder = ConnectionFactoryOptions.builder();
		Field[] fields = r2dbcProperties.getClass().getDeclaredFields();
		for(Field field : fields) {
			try {
				field.setAccessible(true);
				String k = field .getName();
				Object v = field.get(r2dbcProperties);
				if (!StringUtils.isEmpty(v)) {
					v = CONNECT_TIMEOUT_VALUE.equals(k) ? Duration.ofSeconds(3) : v;
					k = USERNAME_KEY.equals(k) ? USER_KEY : k;
					log.info("spring.r2dbc.{}=[{}]", k, v);
					builder.option(Option.valueOf(k), v);
				}
			} catch (IllegalArgumentException | IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		ConnectionFactoryOptions options = builder.build();
		ConnectionFactory connectionFactory = ConnectionFactories.get(options);
		return connectionFactory;
	}

	@Bean
	ReactiveTransactionManager transactionManager(ConnectionFactory connectionFactory) {
		return new R2dbcTransactionManager(connectionFactory);
	}

}

